package com.ruoyi.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.domain.entity.*;
import com.ruoyi.project.domain.query.ProjectCustomQuery;
import com.ruoyi.project.domain.query.ProjectFeeQuery;
import com.ruoyi.project.mapper.*;
import com.ruoyi.project.service.*;
import com.ruoyi.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;


@Service
public class ProjectFeeServiceImpl extends ServiceImpl<ProjectFeeMapper, ProjectFee> implements IProjectFeeService {
    @Resource
    private ProjectFeeMapper projectFeeMapper;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private IProjectParticipanService projectParticipanService;

    @Resource
    private IProjectGjpUserService projectGjpUserService;


    @Resource
    private IProjectAccountingService accountingService;

    @Autowired
    private RedisCache redisCache;
    //
    @Resource
    private ProjectCustomMapper projectCustomMapper;

    @Resource
    private ProjectSaleConfigMapper projectSaleConfigMapper;

    @Resource
    @Lazy
    private IProjectSaleService projectSaleService;


    @Override
    @Async("taskExecutor") // 指定使用的线程池
    public Boolean syncData(List<ProjectFee> list) {
        return this.saveBatch(list);
    }


    @Override
    public void deleteAll(LocalDate threeDaysAgo) {
//        projectFeeMapper.deleteAll(threeDaysAgo);
        projectFeeMapper.deleteAll();
    }

    @Override
    public List<ProjectFee> getAllFee(ProjectFeeQuery query) {

        List<ProjectFee> list = new ArrayList<>();
        String housekeeperProject = query.getHousekeeperProject();

        if (StringUtils.isEmpty(housekeeperProject)) {
            throw new RuntimeException("未关联管家婆项目");
        }

        //1表示重新计算 否则直接取缓存中的
        if (!"1".equals(query.getRefresh())) {
            list = (List<ProjectFee>) redisCache.getCacheObject(housekeeperProject + "fee");
            if (list != null) {
                return list;
            } else {
                list = new ArrayList<>();
            }
        }

        //1.先取出所有参与本项目的人
        LambdaQueryWrapper<ProjectParticipan> joinWrapper = new QueryWrapper<ProjectParticipan>().lambda()
                .eq(query.getProjectNo() != null, ProjectParticipan::getProjectNo, query.getProjectNo());
        // 获取所有参与者
        List<ProjectParticipan> personList = projectParticipanService.list(joinWrapper);

// 获取所有用户，并将其转换为以 userId 为键的 Map，提升查找效率
        List<SysUser> sysUsersList = sysUserService.selectAllUser();

// 存储匹配的用户昵称
        List<String> nickNames = sysUsersList.stream()
                .map(SysUser::getNickName) // 提取每个 SysUser 对象的 nickname 字段
                .filter(Objects::nonNull)  // 过滤掉 null 值（如果 nickname 可能为 null）
                .collect(Collectors.toList()); // 收集结果到 List<String>

        //存储最终结果
        List<ProjectFee> resultFeeList = new ArrayList<>();
        for (String name : nickNames) {
            //用名称去管家婆用户表查对应的id 能查到再去费用表中查有无报销的费用
            LambdaQueryWrapper<ProjectGjpUser> gjpUserWrapper = new QueryWrapper<ProjectGjpUser>().lambda()
                    .eq(ProjectGjpUser::getName, name);
            ProjectGjpUser one = projectGjpUserService.getOne(gjpUserWrapper);
            if (one == null) {
                continue;
            }
            query.setUserId(one.getUserId());
            query.setHousekeeperProject(housekeeperProject);
            /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4 类型是1的为收款    以上取大于0的*/
            LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                    .eq(query.getHousekeeperProject() != null, ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                    .eq(query.getUserId() != null, ProjectFee::getUserId, query.getUserId())
                    .eq(ProjectFee::getUseType, "1")
                    .eq(ProjectFee::getMainType, "36");//有冲红的 去掉大于0 的条件
//                        .gt(ProjectFee::getTotal, 0.1); // 添加 total > 0 的条件
            List<ProjectFee> projectFeeList = projectFeeMapper.selectList(wrapper);
            // 为每个 ProjectFee 对象设置 name
            for (ProjectFee projectFee : projectFeeList) {
                projectFee.setName(name); // 设置 name 属性
            }
            resultFeeList.addAll(projectFeeList);
        }

        redisCache.redisTemplate.opsForValue().set(housekeeperProject + "fee", resultFeeList, 12, TimeUnit.HOURS);
        return resultFeeList;
    }

    @Override
    public List<ProjectFee> getAllFeeByDate(ProjectFeeQuery query) {
        List<ProjectFee> list = new ArrayList<>();
        String housekeeperProject = query.getHousekeeperProject();

        if (StringUtils.isEmpty(housekeeperProject)) {
            throw new RuntimeException("查询管家婆项目失败");
        }

        Long mainId = query.getMainId();

        ProjectCustom projectCustom = projectCustomMapper.selectById(mainId);
        Date startDate = projectCustom.getStartDate();
        Date endDate = projectCustom.getEndDate();

        //去查询往来里面的对应的ID
        //1表示重新计算 否则直接取缓存中的
        if (!"1".equals(query.getRefresh())) {
            list = (List<ProjectFee>) redisCache.getCacheObject(query.getMainId().toString() + "fee");
            if (list != null) {
                return list;
            } else {
                list = new ArrayList<>();
            }
        }


// 获取所有用户，并将其转换为以 userId 为键的 Map，提升查找效率
        List<SysUser> sysUsersList = sysUserService.selectAllUser();

// 存储匹配的用户昵称
        List<String> nickNames = sysUsersList.stream()
                .map(SysUser::getNickName) // 提取每个 SysUser 对象的 nickname 字段
                .filter(Objects::nonNull)  // 过滤掉 null 值（如果 nickname 可能为 null）
                .collect(Collectors.toList()); // 收集结果到 List<String>

        //存储最终结果
        List<ProjectFee> resultFeeList = new ArrayList<>();
        for (String name : nickNames) {
            //用名称去管家婆用户表查对应的id 能查到再去费用表中查有无报销的费用
            LambdaQueryWrapper<ProjectGjpUser> gjpUserWrapper = new QueryWrapper<ProjectGjpUser>().lambda()
                    .eq(ProjectGjpUser::getName, name);
            ProjectGjpUser one = projectGjpUserService.getOne(gjpUserWrapper);
            if (one == null) {
                continue;
            }
            query.setUserId(one.getUserId());
            query.setHousekeeperProject(housekeeperProject);
            /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4 类型是1的为收款    以上取大于0的*/
            LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                    .eq(query.getHousekeeperProject() != null, ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                    .eq(query.getUserId() != null, ProjectFee::getUserId, query.getUserId())
                    .eq(ProjectFee::getUseType, "1")
                    .between(ProjectFee::getSubmitDate, startDate, endDate)
                    .eq(ProjectFee::getMainType, "36");//有冲红的 去掉大于0 的条件
//                        .gt(ProjectFee::getTotal, 0.1); // 添加 total > 0 的条件
            List<ProjectFee> projectFeeList = projectFeeMapper.selectList(wrapper);
            // 为每个 ProjectFee 对象设置 name
            for (ProjectFee projectFee : projectFeeList) {
                projectFee.setName(name); // 设置 name 属性
            }
            resultFeeList.addAll(projectFeeList);
        }

        redisCache.redisTemplate.opsForValue().set(query.getMainId().toString() + "fee", resultFeeList, 12, TimeUnit.HOURS);
        return resultFeeList;
    }


    @Override
    public List<ProjectFee> getReceiveFee(ProjectFeeQuery query) {
        /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4  类型是1的为收款  93是其他收入算到出库单中  以上取大于0的*/
        if (StringUtils.isEmpty(query.getHousekeeperProject())) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                .eq(ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                .eq(ProjectFee::getUseType, "1")
                .in(ProjectFee::getMainType, Arrays.asList("4"))
                .orderByAsc(ProjectFee::getSubmitDate);
        List<ProjectFee> feeList = this.list(wrapper);
        return feeList;
    }

    @Override
    public List<ProjectFee> getReceiveAndOtherFee(ProjectFeeQuery query) {
        /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4  类型是1的为收款  93是其他收入算到出库单中  以上取大于0的*/
        if (StringUtils.isEmpty(query.getHousekeeperProject())) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                .eq(ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                .eq(ProjectFee::getUseType, "1")
                .in(ProjectFee::getMainType, Arrays.asList("4", "93", "66"))
                .orderByAsc(ProjectFee::getSubmitDate);
        List<ProjectFee> feeList = this.list(wrapper);
        return feeList;
    }

    @Override
    public List<ProjectFee> getBalanceFee(ProjectFeeQuery query) {
        //取备注为 专用调整工程材料的费用单 manType是36的
        /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4  类型是1的为收款  93是其他收入算到出库单中  以上取大于0的*/
        if (StringUtils.isEmpty(query.getHousekeeperProject())) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                .eq(ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                .eq(ProjectFee::getUseType, "1")
                .like(ProjectFee::getRemark, "专用调整工程材料的费用单")
                .in(ProjectFee::getMainType, Arrays.asList("666"))
                .orderByAsc(ProjectFee::getSubmitDate);
        List<ProjectFee> feeList = this.list(wrapper);
        return feeList;
    }

    @Override
    public List<ProjectFee> getOtherFee(ProjectFeeQuery query) {
        if (StringUtils.isEmpty(query.getHousekeeperProject())) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                .eq(query.getHousekeeperProject() != null, ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                .eq(ProjectFee::getUseType, "1")
                .in(ProjectFee::getMainType, Arrays.asList("93"))//
                .gt(ProjectFee::getTotal, 0.1); // 添加 total > 0 的条件
        List<ProjectFee> projectFeeList = this.list(wrapper);
        return projectFeeList;
    }


    @Override
    public List<ProjectFee> getReceiveAndPay(ProjectFeeQuery query) {
        /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4  类型是1的为收款  93是其他收入算到出库单中  以上取大于0的*/
        if (StringUtils.isEmpty(query.getHousekeeperProject())) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                .eq(ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                .eq(ProjectFee::getUseType, "1")
                .in(ProjectFee::getMainType, Arrays.asList("4", "66"))
                .orderByAsc(ProjectFee::getSubmitDate);
        List<ProjectFee> feeList = this.list(wrapper);
        return feeList;
    }

    @Override
    public List<ProjectPay> getReceiveAndPayForCustomer(ProjectFeeQuery query) {
        /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4  类型是1的为收款  93是其他收入算到出库单中  以上取大于0的*/
        if (query.getMainId() == null) {
            return new ArrayList<>();
        }

        //查询往来客户 取出起始日期和截止日期

        ProjectCustom projectCustom = projectCustomMapper.selectById(query.getMainId());
        Date startDate = projectCustom.getStartDate();
        Date endDate = projectCustom.getEndDate();
        query.setHousekeeperProject(projectCustom.getCustomerId());
        //只取起始日期和截止日期之间的
        LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                .eq(ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                .eq(ProjectFee::getUseType, "1")
                .in(ProjectFee::getMainType, Arrays.asList("4", "66"))
                .between(ProjectFee::getSubmitDate, startDate, endDate)
                .orderByAsc(ProjectFee::getSubmitDate);
        List<ProjectFee> feeList = projectFeeMapper.selectList(wrapper);

        List<ProjectPay> payList = new ArrayList<>();

        //减去调平的金额
        ProjectPay subPay = new ProjectPay();
        subPay.setReceivedAmount(projectCustom.getSubAmount().negate());
        subPay.setRemark("调平金额");
        payList.add(subPay);

        feeList.forEach(item -> {
            ProjectPay projectPay = new ProjectPay();
            projectPay.setReceivedAmount(item.getTotal());
            projectPay.setPayDate(item.getSubmitDate());
            projectPay.setRemark(item.getRemark());
            projectPay.setSettlementAmount(projectCustom.getTotal());

            projectPay.setHousekeeperProject(item.getHousekeeperProject());
            projectPay.setTotal(item.getTotal());
            projectPay.setUseType(item.getUseType());
            projectPay.setMainType(item.getMainType());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String formatted = sdf.format(item.getSubmitDate());
            projectPay.setSubmitDate(formatted);

            //查询绑定的总金额加起来是否等于实收金额
            // const feeKey = `${row.housekeeperProject}|${row.total}|${row.useType}|${row.mainType}|${row.submitDate}`
            String housekeeperProject = projectPay.getHousekeeperProject();
            BigDecimal total = projectPay.getTotal();
            String useType = projectPay.getUseType();
            String mainType = projectPay.getMainType();
            String submitDate = projectPay.getSubmitDate();
            String feeKey = String.join("|",
                    Objects.toString(housekeeperProject, "null"),
                    total == null ? "null" : total.toPlainString(),
                    Objects.toString(useType, "null"),
                    Objects.toString(mainType, "null"),
                    Objects.toString(submitDate, "null")
            );
            System.out.println(feeKey);

            LambdaQueryWrapper<ProjectSaleConfig> configWrapper = new QueryWrapper<ProjectSaleConfig>().lambda();
            if (StringUtils.isNotEmpty(feeKey)) {
                try {
                    //0000301013|11526|1|4|2025-04-10
                    configWrapper.eq(ProjectSaleConfig::getFeeKey, feeKey);
                    List<ProjectSaleConfig> projectSaleConfigs = projectSaleConfigMapper.selectList(configWrapper);
                    if (projectSaleConfigs != null && projectSaleConfigs.size() > 0) {
                        ProjectSaleConfig projectSaleConfig = projectSaleConfigs.get(0);
                        List<String> saleKey = projectSaleConfig.getSaleKey();
                        BigDecimal currentTotal = BigDecimal.ZERO;

                        for (String key : saleKey) {
                            // 按 | 分割（注意：| 在正则中是特殊字符，需转义为 \\|）
                            String[] parts = key.split("\\|");

                            if (parts.length == 5) {
                                String goodsId = parts[0];
                                String saleDate = parts[1];
                                int amount = Integer.parseInt(parts[2]);
                                String housekeeperProjectConfig = parts[3];
                                String price = String.valueOf(parts[4]);

                                System.out.println("goodsId: " + goodsId);
                                System.out.println("saleDate: " + saleDate);
                                System.out.println("amount: " + amount);
                                System.out.println("housekeeperProjectConfig: " + housekeeperProjectConfig);
                                System.out.println("price: " + price);
                                System.out.println("-------------------");

                                LambdaQueryWrapper<ProjectSale> saleWrapper = new QueryWrapper<ProjectSale>().lambda();
                                saleWrapper.eq(ProjectSale::getHousekeeperProject, housekeeperProjectConfig);
                                saleWrapper.eq(ProjectSale::getSaleDate, saleDate);
                                saleWrapper.eq(ProjectSale::getAmount, -amount);
                                saleWrapper.eq(ProjectSale::getPrice, price);
                                ProjectSale saleOne = projectSaleService.getOne(saleWrapper);
                                currentTotal = currentTotal.add(saleOne.getTotal().negate());
                            }
                        }


//                        ProjectCustomQuery customQuery = new ProjectCustomQuery();
//                        customQuery.setCustomerId(projectCustom.getCustomerId());
//                        Map<String, Object> map = accountingService.saleConfigInfo(customQuery);
//                        List<ProjectSale> saleList = (List<ProjectSale>) map.get("saleList");
//                        //const itemKey = `${item.goodsId}|${item.saleDate}|${item.amount}|${item.housekeeperProject}|${item.price}`;
//                        //
//                        for (ProjectSale projectSale : saleList) {
//
//                        }
                        if (projectPay.getReceivedAmount().compareTo(currentTotal) < 0) {
                            projectPay.setCurrRow("1");
                        } else if (projectPay.getReceivedAmount().compareTo(currentTotal) > 0) {
                            projectPay.setCurrRow("2");
                        } else if (projectPay.getReceivedAmount().compareTo(currentTotal) == 0) {
                            projectPay.setCurrRow("3");
                        }
                        projectPay.setConfigTotal(String.valueOf(currentTotal));
                    }

                } catch (Exception e) {
                    throw new RuntimeException("服务器异常!");
                }
            }
            //找到对应的config  取出saleKey 查询出库单


            payList.add(projectPay);

        });

        return payList;
    }

    @Override
    public BigDecimal getDiscount(ProjectFeeQuery query) {
        /**   根据数据观察  vcType是36 且 useType是1的表示是报销费用  vcType是4  类型是1的为收款  93是其他收入算到出库单中  以上取大于0的*/
        if (StringUtils.isEmpty(query.getHousekeeperProject())) {
            return new BigDecimal("0.00");
        }
        LambdaQueryWrapper<ProjectFee> wrapper = new QueryWrapper<ProjectFee>().lambda()
                .eq(ProjectFee::getHousekeeperProject, query.getHousekeeperProject())
                .eq(ProjectFee::getUseType, "2")
                .gt(ProjectFee::getTotal, 0.1)
                .in(ProjectFee::getMainType, Arrays.asList("11"))
                .orderByAsc(ProjectFee::getSubmitDate);
        List<ProjectFee> feeList = this.list(wrapper);
        BigDecimal discount = BigDecimal.ZERO;
        for (ProjectFee projectFee : feeList) {
            discount = discount.add(projectFee.getTotal());
        }
        return discount;
    }

}
